// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: ziyan
#pragma once

#include <algorithm>
#include <functional>
#include <map>
#include <string>
#include <vector>

#include "coin2/exchange/base/feed/processor.h"

namespace coin2::exchange::bittrex::feed_v3 {
namespace impl {
using coin2::exchange::feed::WebsocketConfig;

class BittrexRequestGenerator : public base::feed::RequestGenerator {
 public:
  explicit BittrexRequestGenerator(const WebsocketConfig* ws_config) : config_(ws_config) {}
  std::vector<std::string> GenerateRequests(
      const std::vector<std::string>& channels,
      const std::vector<std::string>& symbols,
      const std::map<std::string, std::string>& channel_templates,
      const std::string& request_template) override {
    std::vector<std::string> reqs;
    std::vector<std::string> reqs_kline;
    std::vector<std::string> reqs_others;
    std::vector<std::string> ch = channels;
    std::vector<std::string> ch_kline;

    auto iter = ch.begin();
    while (iter != ch.end()) {
      if (StringStartsWith(*iter, "kline_rest")) {
        ch_kline.push_back(*iter);
        iter = ch.erase(iter);
      } else {
        iter++;
      }
    }

    if (!ch_kline.empty()) {
      for (auto& ch_k : ch_kline) {
        std::string c = channel_templates.at(ch_k);
        for (auto& symbol : symbols) {
          std::string c_copy = c;
          boost::replace_all(c_copy, "{}", symbol);
          reqs_kline.emplace_back(c_copy);
        }
      }
    }
    reqs.insert(reqs.end(), reqs_kline.begin(), reqs_kline.end());

    if (request_template.find("{json_list}") != std::string::npos) {
      std::vector<std::string> str_jsons;
      for (const auto& symbol : symbols) {
        for (const auto& channel_name : ch) {
          std::string c = channel_templates.at(channel_name);
          boost::replace_all(c, "{}", symbol);
          c = "\"" + c + "\"";
          str_jsons.push_back(c);
        }
      }
      if (str_jsons.size() != 0) {
        std::string s = request_template;
        boost::replace_all(s, "{json_list}", "[" + Join(str_jsons) + "]");
        reqs_others.push_back(s);
      }
    }

    reqs.insert(reqs.end(), reqs_others.begin(), reqs_others.end());
    return reqs;
  }

private:
 const WebsocketConfig* config_;
};

}  // namespace impl
using impl::BittrexRequestGenerator;
}  // namespace coin2::exchange::bittrex::feed_v3